#ifndef __UBT_YAML_CONFIG_H__
#define __UBT_YAML_CONFIG_H__

#include <iostream>
#include <string>
#include <jsoncpp/json/json.h>
#include <yaml-cpp/yaml.h>
#include <yaml-cpp/node/parse.h>

#include "config.h"
#include <ubt_mqtt/node.h> 
using namespace ubt;

namespace YAML
{
template<>
struct convert<mqtt_paramer_t>
{
    static bool decode(const Node &node, mqtt_paramer_t &paramer)
    {
        paramer.name     = node["service_name"].as<std::string>();
        paramer.password = node["service_pswd"].as<std::string>();
        paramer.address  = node["server_address"].as<std::string>();
        paramer.port     = node["service_port"].as<short>();
        return true;
    }
};

template<>
struct convert<map_origin_info_t>
{
    static bool decode(const Node &node, map_origin_info_t &paramer)
    {
        if (node["image"])
        {
            paramer.image = node["image"].as<std::string>();
        }

        if (node["resolution"])
        {
            paramer.resolution = node["resolution"].as<float>();
        }

        if (node["negate"])
        {
            paramer.negate = node["negate"].as<float>();
        }

        if (node["occupied_thresh"])
        {
            paramer.occupied_thresh = node["occupied_thresh"].as<float>();
        }

        if (node["free_thresh"])
        {
            paramer.free_thresh = node["free_thresh"].as<float>();
        }

        if (node["origin"])
        {
            paramer.origin.x = node["origin"][0].as<float>();
            paramer.origin.y = node["origin"][1].as<float>();
            paramer.origin.theta = node["origin"][2].as<float>();
        }

        if (node["map_hash"])
        {
            paramer.map_hash = node["map_hash"].as<std::string>();
        }

        if (node["map"])
        {
            paramer.id = node["map"][0].as<std::string>();
            paramer.name = node["map"][1].as<std::string>();
            paramer.code = node["map"][2].as<std::string>();
        }

        return true;
    }
};

template<>
struct convert<task_info_t>
{
    static bool decode(const Node &node, task_info_t &paramer)
    {
        paramer.id   = node[0].as<std::string>();
        paramer.name = node[1].as<std::string>();
        paramer.code = node[2].as<std::string>();
        return true;
    }
};
}

namespace ubt_yaml {
template<class T>
inline static bool getValue(const std::string& fileName, const std::string &key, T& paramer)
{
    YAML::Node config;

    try
    {
        config = YAML::LoadFile(fileName);
    }
    catch(YAML::BadFile &e)
    {
        std::cerr << e.what() << std::endl;
        return false;
    }

    if (key != "")
        paramer = config[key].as<T>();
    else
        paramer = config.as<T>();

    return true;
}

inline static bool JsonToYaml(const Json::Value& root, YAML::Node &node)
{
    if (root.type() == Json::arrayValue)
    {
        auto size = root.size();
        for (auto i = 0; i < size; i++)
        {
            if (root[i].type() == Json::objectValue)
            {
                YAML::Node clild_node;
                JsonToYaml(root[i], clild_node);
                node.push_back(clild_node);
            }
            else
            {
                node.push_back(root[i].asString());
            }
        }

        return true;
    }

    Json::Value::Members mem = root.getMemberNames();

    for (auto iter = mem.begin(); iter != mem.end(); iter++)  
    {
        if (root[*iter].type() == Json::arrayValue)
        {
            auto size = root[*iter].size();
            for (auto i = 0; i < size; i++)
            {
                if (root[*iter][i].type() == Json::objectValue)
                {
                    YAML::Node clild_node;
                    JsonToYaml(root[*iter][i], clild_node);
                    node[*iter].push_back(clild_node);
                }
                else
                {
                    node[*iter].push_back(root[*iter][i].asString());
                }
            }
        }
        else if (root[*iter].type() == Json::objectValue)
        {
            YAML::Node clild_node;
            JsonToYaml(root[*iter], clild_node);
            node[*iter].push_back(clild_node);
        }
        else if (root[*iter].type() == Json::stringValue)
        {
            node[*iter] = root[*iter].asString();
        }  
        else if (root[*iter].type() == Json::realValue)
        {
            node[*iter] = root[*iter].asDouble();
        }
        else if (root[*iter].type() == Json::uintValue)
        {
            node[*iter] = root[*iter].asUInt();
        }
        else
        {
            node[*iter] = root[*iter].asInt();
        }
    }

    return true;
}

}

#endif // !__UBT_YAML_CONFIG_H__

